home *** CD-ROM | disk | FTP | other *** search
/ Aminet 25 / Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso / Aminet / hard / drivr / cnetdevice.lha / cnetdevice / src / cnetdevice.asm < prev    next >
Assembly Source File  |  1998-04-23  |  54KB  |  1,837 lines

  1. ;---------------------------------------------------------------------------
  2. ;                    PCMCIA ethernet card driver for A1200
  3. ;---------------------------------------------------------------------------
  4. ;
  5. ; HISTORY:
  6. ;
  7. ; 10-4-97  v0.1 - Created by Bruce Abbott (bhabbott@inhb.co.nz)
  8. ;                      *** First Aminet Release ***
  9. ;
  10. ; 29-4-97  v0.2 - Implemented CMD_ONLINE/OFFLINE/FLUSH (for Miami).
  11. ;
  12. ;               - Enabled interrupts during RemoteWrite (no more serial
  13. ;                 port overruns!).
  14. ;
  15. ; 6-5-97   v0.3 - Added a flag so that we won't try to ReleaseCard()
  16. ;                 unless there was a successful OwnCard()!
  17. ;
  18. ; 17-5-97  v0.4 - CMD_CONFIGINTERFACE now overrides the default hardware
  19. ;                 address (for Maimi).
  20. ;
  21. ;               - Device now goes offline if the PCMCIA card is removed.
  22. ;
  23. ;               - CMD_ONEVENT implemented.
  24. ;
  25. ;               - Loosened hardware address verification to accept the
  26. ;                 Accton EN2216.
  27. ;
  28. ;               - Unrolled loops to improve data transfer speed. Now
  29. ;                 about 20% faster on an unexpanded A600.
  30. ;
  31. ;               - Hack to fix problem with missed interrupts. Now we
  32. ;                 clear the Gayle interrupt bits instead of letting
  33. ;                 card.resource do it for us.
  34. ;
  35. ;                        *** Second Aminet Release ***
  36. ;
  37. ; 29-7-97  v0.5 - Accepts 802.3 packets (untested).
  38. ;
  39. ;               - Sets BROADCAST bit in io_flags when appropriate.
  40. ;
  41. ;               - Now examines PCMCIA attribute memory to determine
  42. ;                 value to write into Card Configuration Register.
  43. ;
  44. ;               - If attribute memory not found, tries to open the file
  45. ;                 "s:cnetdev.config" to get Card Configuration Register
  46. ;                 offset, Configuration ID, and ROM Station Address.
  47. ;
  48. ;                        *** Third Aminet Release ***
  49. ;
  50. ;22-12-97 v0.6 - I/O addressing now supports 64KByte range (was 1KB).
  51. ;
  52. ;              - Tighter data transfer loops, slightly faster on '030.
  53. ;
  54. ;              - Accepts all Card Configuration Register address sizes.
  55. ;
  56. ;              - Removed cnet.config stuff (replaced with hardware mod).
  57. ;
  58. ;              - Now cards are hot-swappable.
  59. ;
  60. ;              - Un-supported commands now return S2ERR_NOT_SUPPORTED.
  61. ;
  62. ;                        *** 4th Aminet Release ***
  63. ;
  64. ;21-4-98 v0.7  - fixed harmless bug in init_nic - remote DMA timeout test
  65. ;                could not fail!
  66. ;
  67. ;              - Now remembers copytobuf/copyfrombuf tags for each opener.
  68. ;                Allows simultaneous use of eg. AmiTCP and Envoy.
  69. ;
  70. ;              - OnEvent types ONLINE and OFFLINE now return immediately
  71. ;                if the device is already in the wanted state.
  72. ;
  73. ;                        *** 5th Aminet Release ***
  74.  
  75. ;debug = 1
  76.  
  77.  opt i-,d-
  78.  
  79.  output devs:networks/cnet.device
  80.  
  81.  include amiga.i              ; commodore includes (WB1.3)
  82.  include pcmcia.i             ; card.resource etc.
  83.  include sanaii.i             ; the essential network stuff
  84.  include cnet.i               ; hardware specific stuff
  85.  
  86.  
  87. VERSION  = 0
  88. REVISION = 7
  89.  
  90.  
  91. ; 1uS delay before nic register access
  92. ; May not be required with slower CPUs.
  93.  
  94. delay MACRO
  95. ; tst.b   $bfe001             ; at least 1uS, even on fast machines
  96.  ENDM
  97.  
  98. ;===========================================================================
  99.  
  100.     Section 0,CODE
  101.  
  102. start_exe:
  103.  moveq   #-1,D0   ; it's a device, not an application!
  104.  rts
  105.  
  106. romtag:
  107.  dc.w    RTC_MATCHWORD   ; RT_MATCHWORD
  108.  dc.l    romtag          ; RT_MATCHTAG
  109.  dc.l    Endcode         ; RT_ENDSKIP
  110.  dc.b    RTF_AUTOINIT    ; RT_FLAGS
  111.  dc.b    VERSION         ; RT_VERSION
  112.  dc.b    NT_DEVICE       ; RT_TYPE
  113.  dc.b    0               ; RT_PRI
  114.  dc.l    DeviceName      ; RT_NAME
  115.  dc.l    IDString        ; RT_IDSTRING
  116.  dc.l    Init            ; RT_INIT
  117.  
  118. Init:
  119.  dc.l    dd_extsize      ; data space size
  120.  dc.l    funcTable       ; pointer to function initializers
  121.  dc.l    dataTable       ; pointer to data initializers
  122.  dc.l    initRoutine     ; routine to run at startup
  123.  
  124. funcTable:
  125.  dc.w  -1
  126.  dc.w  Open_Device-funcTable
  127.  dc.w  Close_Device-funcTable
  128.  dc.w  _DevExpunge-funcTable
  129.  dc.w  _Null-funcTable
  130.  dc.w  _DevBeginIO-funcTable
  131.  dc.w  _DevAbortIO-funcTable
  132.  dc.w  -1
  133.  
  134. dataTable:
  135.  INITBYTE LN_TYPE,NT_DEVICE
  136.  INITLONG LN_NAME,DeviceName
  137.  INITBYTE LIB_FLAGS,LIBF_SUMUSED!LIBF_CHANGED
  138.  INITWORD LIB_VERSION,VERSION
  139.  INITWORD LIB_REVISION,REVISION
  140.  INITLONG LIB_IDSTRING,idString
  141.  dc.w   0
  142.  
  143.  include debugs.i
  144.  
  145. ;=======================================================
  146. ;                      initRoutine
  147. ;=======================================================
  148. ;
  149. ; Called after device has been allocated.
  150. ; This routine is single threaded
  151. ;
  152. ; input:   a0 = seglist
  153. ;          d0 = device
  154. ;
  155. initRoutine:
  156.  movem.l d1-d7/a0-a5,-(A7)
  157.  move.l  d0,a5
  158.  move.l  a0,dd_SegList(a5)  ; seglist for expunge
  159.  move.l  4,execbase         ; local copy of execbase
  160.  move.l  a5,d0
  161.  movem.l (A7)+,d1-d7/a0-a5
  162.  rts
  163.  
  164. _Null:
  165.  moveq   #0,d0
  166.  rts
  167.  
  168. ;=================================================================
  169. ;                         Open Device
  170. ;=================================================================
  171. ;
  172. ; error = Open_Device(device, ioreq, unitnum, flags)
  173. ;  d0                   a6      a1     d0      d1
  174. ;
  175. Open_Device:
  176.  bug     <"cnet: OpenDevice(ioreq $%lx, unit %ld)",10>,a1,d0
  177.  movem.l D2-D4/A2-A4/A6,-(A7)
  178.  move.l  A6,A3                       ; a3 = device
  179.  move.l  A1,A4                       ; a4 = ioreq
  180.  move.l  D0,D4                       ; d4 = unit
  181.  move.l  a3,a1
  182.  bsr     init_device                 ; init device data structures
  183.  move.l  a3,a0
  184.  move.l  a4,a1
  185.  move.l  d4,d0
  186.  bsr     Open_Unit                   ; open unit
  187.  move.l  d0,io_unit(a4)
  188.  beq.s   .error
  189.  btst    #DDB_NICUP,dd_flags(a3)     ; nic already initialised ?
  190.  bne.s   .ok
  191.  move.l  a3,a1
  192.  bsr     init_card                   ; init PCMCIA card
  193.  tst.l   d0
  194.  bne.s   .error
  195.  move.l  a3,a1
  196.  bsr     init_nic                    ; set up nic
  197.  tst.l   d0
  198.  beq.s   .ok
  199. .error:
  200.  move.l  dd_cardres(a3),d0           ; did card.resource open ?
  201.  beq.s   .nocard
  202.  move.l  d0,a6
  203.  bclr    #DDB_OWNED,dd_flags(a3)     ; did we own card ?
  204.  beq.s   .nocard
  205.  lea     dd_cardhandle(a3),a1
  206.  moveq   #CARDF_REMOVEHANDLE,d0
  207.  jsr     _LVOReleaseCard(a6)         ; release card
  208. .nocard:
  209.  moveq   #IOERR_OPENFAIL,d0          ; error, opendevice failed!
  210.  move.b  d0,io_error(a4)
  211.  move.l  d0,io_device(a4)
  212.  bug     <"cnet: opendevice failed!",10,10>
  213.  bra.s   .done
  214. .ok:
  215.  btst    #DDB_OFFLINE,dd_flags(a3)   ; previously put offline ?
  216.  bne.s   .opened
  217.  bset    #DDB_ONLINE,dd_flags(a3)    ; ready to accept packets
  218. .opened:
  219.  moveq   #0,d0
  220.  move.b  d0,io_error(a4)             ; complete the ioreq
  221.  move.b  #NT_REPLYMSG,ln_type(a4)
  222.  addq.w  #1,lib_OpenCnt(a3)          ; opened successfully
  223.  bug     <"cnet: opendevice OK",10,10>
  224. .done:
  225.  movem.l (A7)+,D2-D4/A2-A4/A6
  226.  rts
  227.  
  228.  
  229. ;===============================================================
  230. ;                 unit=Open Unit(device, ioreq, unitnum)
  231. ;                  d0              a0      a1     d0
  232. ;===============================================================
  233. ;
  234. ; Get the caller's buffer copy callback vectors
  235. ;
  236. Open_Unit:
  237.  movem.l D2-D6/A2-A5,-(A7)
  238.  move.l  A0,A4                    ; A4 = device
  239.  move.l  A1,A5                    ; A5 = ioreq
  240.  tst.l   D0                       ; only unit 0 is supported
  241.  bne     .error
  242.  move.l  ios2_buffermanagement(A5),D0  ; tag list supplied?
  243.  beq     .ok
  244.  moveq   #0,D2                    ; d2 = tags found
  245.  move.l  D0,A0                    ; a0 = tag list
  246. .next_tag:
  247.  move.l  (A0)+,D0                 ; d0 = tag number
  248.  beq     .got_tags                ; end of tag list?
  249.  move.l  (A0)+,D1                 ; d1 = tag value
  250.  cmp.l   #S2_COPYFROMBUFF,D0
  251.  beq.s   .from                    ; tag_copyfrombuf ?
  252.  cmp.l   #S2_COPYTOBUFF,D0
  253.  bne.s   .next_tag                ; tag_copytobuf ?
  254. .to:
  255.  move.l  D1,D5                    ; d5 = copy2buf
  256.  bset    #0,D2                    ; got the tag
  257.  bra     .next_tag
  258. .from:
  259.  move.l  D1,D6                    ; d6 = copyfrombuf
  260.  bset    #1,D2                    ; got the tag
  261.  bra     .next_tag
  262. .got_tags:
  263.  and.b   #3,d2
  264.  cmp.w   #3,D2                    ; got both tags ?
  265.  bne.s   .error
  266.  moveq   #bufman_sizeof,d0
  267.  moveq   #0,d1
  268.  move.l  execbase(pc),a6          ; allocate memory for bufman vectors
  269.  jsr     _LVOAllocMem(a6)
  270.  move.l  d0,ios2_buffermanagement(a5)  ; return bufman node
  271.  beq.s   .error
  272.  move.l  d0,a1
  273.  move.l  d5,bufman_copytobuf(a1)
  274.  move.l  d6,bufman_copyfrombuf(a1)
  275.  bug     <"cnet: addbufman $%lx $%lx $%lx",10>,a1,d5,d6
  276.  lea     dd_bufmanlist(a4),a0
  277.  jsr     _LVOAddHead(a6)          ; add to buffer management list
  278.  bra.s   .ok
  279. .error:
  280.  moveq   #0,d0                    ; return error
  281.  bra.s   .done
  282. .ok:
  283.  moveq   #1,d0                    ; return OK
  284. .done:
  285.  movem.l (A7)+,D2-D6/A2-A5
  286.  rts
  287.  
  288.  
  289. ;============================================================
  290. ;                      Expunge Device
  291. ;============================================================
  292. ;
  293. ; called when system wants us to close down
  294. ;
  295. _DevExpunge:
  296.  tst.w   lib_opencnt(a6)
  297.  bne.s   .done
  298.  bset    #LIBB_DELEXP,lib_flags(a6)
  299. .done:
  300.  moveq   #0,d0
  301.  rts
  302.  
  303.  
  304.  
  305. ;============================================================
  306. ;                      Close Device
  307. ;============================================================
  308. ;
  309. ;  Seglist = CloseDevice(ioreq,device)
  310. ;    d0                    a1    a6
  311. ;
  312. Close_Device:
  313.  bug     <"cnet: CloseDevice(io$%lx",10>,a1
  314.  movem.l a2/a3/a6,-(sp)
  315.  move.l  a1,a3                        ; a3 = ioreq
  316.  move.w  lib_OpenCnt(a6),d0
  317.  beq.s   .done                        ; already closed ?
  318.  subq.w  #1,d0
  319.  move.w  d0,lib_OpenCnt(a6)
  320.  move.l  ios2_buffermanagement(a3),d0
  321.  beq.s   .done                        ; got a buffermanagement pointer ?
  322.  move.l  d0,a2
  323.  move.l  a2,a1
  324.  bug     <"cnet: remove bufman $%lx",10>,a1
  325.  move.l  execbase(pc),a6
  326.  jsr     _LVORemove(a6)               ; remove bufman struct from list
  327.  move.l  a2,a1
  328.  moveq   #bufman_sizeof,d0
  329.  jsr     _LVOFreeMem(a6)              ; discard buffer management struct
  330. .done:
  331.  movem.l (sp)+,a2/a3/a6
  332.  moveq   #0,d0                        ; no seglist, cannot be unloaded!
  333.  rts
  334.  
  335.  
  336. ;===============================================================
  337. ;                       Dev_BeginIO
  338. ;===============================================================
  339. ; the entry point for all device commands
  340. ;
  341. _DevBeginIO:
  342.  move.b  #NT_MESSAGE,ln_type(A1) ; make sure type is message
  343.  moveq   #0,d0
  344.  move.w  io_command(A1),D0       ; get command number
  345.  cmp.w   #S2_END,D0
  346.  bhs.s   .error                  ; valid command?
  347.  lsl.w   #2,D0
  348.  move.l  cmds(PC,D0.w),D0        ; get command vector
  349.  bne.s   .ok
  350. .error:
  351.  move.b  #IOERR_NOCMD,io_error(A1)
  352.  bra     TermIO                  ; return invalid command
  353. .ok:
  354.  clr.b   io_error(A1)            ; no errors yet
  355.  move.l  D0,A0
  356.  jmp     (A0)                    ; jump to command
  357.  
  358.  
  359. ; command vectors
  360.  
  361. cmds:
  362.  dc.l    0                           ;  0
  363.  dc.l    0                           ;  1
  364.  dc.l    devcmd_read                 ;  2 = cmd_read
  365.  dc.l    devcmd_write                ;  3 = cmd_write
  366.  dc.l    0                           ;  4
  367.  dc.l    0                           ;  5
  368.  dc.l    0                           ;  6
  369.  dc.l    0                           ;  7
  370.  dc.l    devcmd_flush                ;  8 = cmd_flush
  371.  dc.l    devcmd_devicequery          ;  9 = S2_DEVICEQUERY
  372.  dc.l    devcmd_getstationaddress    ;  10= S2_GETSTATIONADDRESS
  373.  dc.l    devcmd_configinterface      ;  11= S2_CONFIGINTERFACE
  374.  dc.l    0                           ;  12
  375.  dc.l    0                           ;  13
  376.  dc.l    devcmd_nosupport            ;  14= S2_ADDMULTICASTADDRESS
  377.  dc.l    devcmd_nosupport            ;  15= S2_DELMULTICASTADDRESS
  378.  dc.l    devcmd_nosupport            ;  16= S2_MULTICAST
  379.  dc.l    devcmd_broadcast            ;  17= S2_BROADCAST
  380.  dc.l    devcmd_tracktype            ;  18= S2_TRACKTYPE
  381.  dc.l    devcmd_untracktype          ;  19= S2_UNTRACKTYPE
  382.  dc.l    devcmd_nosupport            ;  20= S2_GETTYPESTATS
  383.  dc.l    devcmd_nosupport            ;  21= S2_GETSPECIALSTATS
  384.  dc.l    devcmd_nosupport            ;  22= S2_GETGLOBALSTATS
  385.  dc.l    devcmd_onevent              ;  23= S2_ONEVENT
  386.  dc.l    devcmd_nosupport            ;  24= S2_READORPHAN
  387.  dc.l    devcmd_online               ;  25= S2_ONLINE
  388.  dc.l    devcmd_offline              ;  26= S2_OFFLINE
  389.  
  390.  
  391. ;====================================================================
  392. ;                              Abort_IO
  393. ;====================================================================
  394. ;
  395. ;                   try to cancel a pending ioreq
  396. ;
  397. _DevAbortIO:
  398.  movem.l A2/A6,-(A7)
  399.  move.l  A1,A2
  400.  moveq   #-1,D0                           ; assume failure
  401.  cmp.b   #NT_MESSAGE,ln_type(A2)          ; only cancel queued ioreq's
  402.  bne.s   .done
  403.  move.l  execbase(PC),A6
  404.  jsr     _LVODisable(A6)
  405.  move.l  A2,A1
  406.  jsr     _LVORemove(A6)                   ; remove ioreq from list
  407.  move.b  #IOERR_ABORTED,io_error(A2)
  408.  move.l  A2,A1
  409.  jsr     _LVOReplyMsg(A6)                 ; reply to originator's message
  410.  jsr     _LVOEnable(A6)
  411.  moveq   #0,D0                            ; aborted OK
  412. .done:
  413.  movem.l (A7)+,A2/A6
  414.  rts
  415.  
  416.  
  417.  
  418. ;===========================================================
  419. ;                      termio(ioreq)
  420. ;                               a1
  421. ;===========================================================
  422. ;
  423. ; return completed ioreq to sender.
  424. ;
  425. TermIO:
  426.  movem.l A2/A6,-(A7)
  427.  move.l  A1,A2
  428.  move.b  io_error(a1),d0             ; completed OK ?
  429.  beq.s   .noerr
  430.  move.l  io_device(a2),A0
  431.  moveq   #S2EVENT_ERROR,D0
  432.  bsr     DoEvent                     ; do event for error
  433. .noerr:
  434.  move.b  #NT_REPLYMSG,ln_type(A2)
  435.  btst    #IOB_QUICK,io_flags(A2)
  436.  bne.s   .quick                      ; does sender need a reply ?
  437.  move.l  A2,A1
  438.  move.l  execbase(PC),A6
  439.  jsr     _LVOReplyMsg(A6)            ; send reply
  440. .quick
  441. .done:
  442.  movem.l (A7)+,A2/A6
  443.  rts
  444.  
  445.  
  446.  
  447.  
  448. ;====================================================
  449. ;                     CMD_READ
  450. ;====================================================
  451. ;
  452. devcmd_read:
  453.  movem.l A2/A3/A6,-(A7)
  454.  move.l  A1,A2                           ; A2 = ioreq
  455.  move.l  io_device(A2),A3
  456.  btst    #DDB_CONFIGURED,dd_flags(A3)    ; configured ?
  457.  bne.s   .configured
  458.  move.b  #S2ERR_BAD_STATE,io_error(A2)
  459.  moveq   #S2WERR_NOT_CONFIGURED,D0
  460.  move.l  D0,ios2_WireError(A2)           ; error, device is not configured
  461.  bra.s   .error
  462. .configured:
  463.  bclr    #IOB_QUICK,io_flags(A2)         ; must be queued
  464.  move.l  execbase(PC),A6
  465.  jsr     _LVODisable(A6)
  466.  lea     dd_readlist(A3),A0
  467.  move.l  A2,A1
  468.  jsr     _LVOAddTail(A6)                 ; add ioreq to read queue
  469.  jsr     _LVOEnable(A6)
  470.  bra.s   .done
  471. .error:
  472.  move.l  A2,A1
  473.  bsr     TermIO                          ; terminate with error
  474. .done:
  475.  movem.l (A7)+,A2/A3/A6
  476.  rts
  477.  
  478.  
  479. ;======================================================
  480. ;                      CMD_WRITE
  481. ;======================================================
  482. ;
  483. devcmd_write:
  484.  movem.l A2/A3/A6,-(A7)
  485.  move.l  A1,A2                            ; A2 = ioreq
  486.  move.l  io_device(A2),A3
  487.  btst    #DDB_ONLINE,dd_flags(A3)         ; online ?
  488.  bne.s   .online
  489.  move.b  #S2ERR_OUTOFSERVICE,io_error(A2)
  490.  moveq   #S2WERR_UNIT_OFFLINE,D0
  491.  move.l  D0,ios2_WireError(A2)            ; error, device is offline
  492.  bra     .error
  493. .online:
  494.  btst    #DDB_CONFIGURED,dd_flags(A3)     ; configured ?
  495.  bne.s   .configured
  496.  move.b  #S2ERR_BAD_STATE,io_error(A2)
  497.  moveq   #S2WERR_NOT_CONFIGURED,D0
  498.  move.l  D0,ios2_WireError(A2)            ; error, not configured
  499.  bra     .error
  500. .configured:
  501.  btst    #SANA2IOB_RAW,io_flags(A2)       ; raw packets ?
  502.  beq.s   .cooked
  503.  move.l  ios2_DataLength(A2),D1
  504.  cmp.l   #RAWPKT_SIZE,D1
  505.  bls.s   .goodlen                         ; check packet size
  506.  bra.s   .toobig
  507. .cooked:
  508.  move.l  ios2_DataLength(A2),D1
  509.  cmp.l   #ETHERPKT_SIZE,D1
  510.  bls.s   .goodlen
  511. .toobig:
  512.  move.b  #S2ERR_MTU_EXCEEDED,io_error(A2) ; oops! packet too big
  513.  clr.l   ios2_WireError(A2)
  514.  bra     .error
  515. .goodlen:
  516.  bclr    #IOB_QUICK,io_flags(A2)          ; must be queued
  517.  move.l  execbase(PC),A6
  518.  jsr     _LVODisable(A6)
  519.  lea     dd_writelist(A3),A0
  520.  move.l  A2,A1
  521.  jsr     _LVOAddTail(A6)                  ; add ioreq to write queue
  522.  jsr     _LVOEnable(A6)
  523.  lea     dd_txint(A3),A1
  524.  jsr     _LVOCause(A6)                    ; start tx
  525.  bra.s   .done
  526. .error:
  527.  move.l  A2,A1
  528.  bsr     TermIO                           ; terminate with error
  529. .done:
  530.  movem.l (A7)+,A2/A3/A6
  531.  rts
  532.  
  533.  
  534. ;==============================================
  535. ;                CMD_FLUSH
  536. ;==============================================
  537. ;
  538. devcmd_flush:
  539.  movem.l A1/A2/A6,-(A7)
  540.  move.l  io_device(A1),A2
  541.  move.l  execbase(PC),A6
  542.  jsr     _LVODisable(A6)
  543.  bra.s   .flushreads
  544. .readloop:
  545.  move.l  D0,A1
  546.  move.b  #IOERR_ABORTED,io_error(A1)
  547.  jsr     _LVOReplyMsg(A6)             ; abort all Read requests
  548. .flushreads:
  549.  lea     dd_readlist(A2),A0
  550.  jsr     _LVORemHead(A6)
  551.  tst.l   D0
  552.  bne.s   .readloop
  553.  bra.s   .flushwrites
  554. .writeloop:
  555.  move.l  D0,A1
  556.  move.b  #IOERR_ABORTED,io_error(A1)
  557.  jsr     _LVOReplyMsg(A6)             ; abort all Write requests
  558. .flushwrites:
  559.  lea     dd_writelist(A2),A0
  560.  jsr     _LVORemHead(A6)
  561.  tst.l   D0
  562.  bne.s   .writeloop
  563.  bra.s   .flushevents
  564. .eventloop:
  565.  move.l  D0,A1                        ; abort all Event requests
  566.  move.b  #IOERR_ABORTED,io_error(A1)
  567.  jsr     _LVOReplyMsg(A6)
  568. .flushevents:
  569.  lea     dd_eventlist(A2),A0
  570.  jsr     _LVORemHead(A6)
  571.  tst.l   D0
  572.  bne.s   .eventloop
  573.  jsr     _LVOEnable(A6)
  574.  movem.l (A7)+,A1/A2/A6
  575.  bra     TermIO
  576.  
  577.  
  578. ;==============================================
  579. ;               CMD_ONLINE
  580. ;==============================================
  581. ;
  582. ;         Try to put device online
  583. ;
  584. devcmd_online:
  585.  bug     <"cnet: cmd_online",10>
  586.  move.l  a1,-(a7)
  587.  move.l  io_device(a1),a0
  588.  btst    #DDB_CONFIGURED,dd_flags(a0)   ; won't go online unless configured!
  589.  beq.s   .error
  590.  btst    #DDB_NICUP,dd_flags(a0)        ; nic initialised ?
  591.  beq.s   .error
  592.  bclr    #DDB_OFFLINE,dd_flags(a0)
  593.  bset    #DDB_ONLINE,dd_flags(a0)       ; already online ?
  594.  bne.s   .done
  595.  move.b  dd_rcr(a0),nic_rcr             ; set receiver to normal mode
  596.  moveq   #S2EVENT_ONLINE,D0
  597.  bsr     DoEvent                        ; return any ONLINE events
  598.  bra.s   .done
  599. .error:
  600.  move.b  #S2ERR_OUTOFSERVICE,io_error(a1)
  601.  moveq   #S2WERR_UNIT_OFFLINE,d0
  602.  move.l  d0,ios2_wireerror(a1)
  603. .done:
  604.  move.l  (a7)+,a1
  605.  bra     TermIO
  606.  
  607.  
  608. ;==============================================
  609. ;               CMD_OFFLINE
  610. ;==============================================
  611. ;
  612. ;           take device offline
  613. ;
  614. devcmd_offline:
  615.  bug     <"cnet: cmd_offline",10>
  616.  move.l  a1,-(a7)
  617.  move.l  io_device(a1),a0
  618.  bset    #DDB_OFFLINE,dd_flags(a0)
  619.  bclr    #DDB_ONLINE,dd_flags(a0)       ; already offline ?
  620.  beq.s   .done
  621.  btst    #DDB_NICUP,dd_flags(a0)
  622.  beq.s   .nicoff
  623.  move.b  #DSRC_MON,nic_rcr              ; set receiver to monitor mode
  624. .nicoff:
  625.  moveq   #S2EVENT_OFFLINE,D0
  626.  bsr     DoEvent                        ; return any OFFLINE events
  627. .done:
  628.  move.l  (a7)+,a1
  629.  bra     TermIO
  630.  
  631.  
  632. ;==============================================
  633. ;               CMD_ONEVENT
  634. ;==============================================
  635. ;
  636. ;         queue up event requests
  637. ;
  638. ;  online/offline return immediately if the
  639. ;  conditon is meet.
  640. ;
  641. ;
  642. devcmd_onevent:
  643.  bug     <"cnet: cmd_OnEvent $%08lx ">,ios2_wireerror(a1)
  644.  movem.l a1/a6,-(a7)
  645.  move.l  ios2_wireerror(a1),d0
  646.  and.l   #S2EVENT_ONLINE,d0          ; waiting for online event ?
  647.  beq.s   .noton
  648.  btst    #DDB_ONLINE,dd_flags(a1)    ; currently online ?
  649.  bne.s   .rtn
  650.  bra.s   .queue
  651. .noton:
  652.  move.l  ios2_wireerror(a1),d0
  653.  and.l   #S2EVENT_OFFLINE,d0         ; waiting for offline event ?
  654.  beq.s   .queue
  655.  btst    #DDB_ONLINE,dd_flags(a1)    ; currently offline ?
  656.  bne.s   .queue
  657. .rtn:
  658.  bug     <"is (on|off)line",10>
  659.  move.l  d0,ios2_wireerror(a1)       ; return immediately
  660.  clr.b   io_error(a1)
  661.  bra.s   .done
  662. .queue:
  663.  bug     <"queued",10>
  664.  move.l  io_device(a1),a0
  665.  bclr    #IOB_QUICK,io_flags(a1)     ; must be queued
  666.  move.l  execbase(PC),A6
  667.  jsr     _LVODisable(A6)
  668.  lea     dd_eventlist(A0),A0
  669.  jsr     _LVOAddTail(A6)             ; add ioreq to event queue
  670.  jsr     _LVOEnable(A6)
  671. .done:
  672.  movem.l (a7)+,a1/a6
  673.  bra     TermIO
  674.  
  675.  
  676.  
  677.  
  678. ;==============================================
  679. ;             CMD_DEVICEQUERY
  680. ;==============================================
  681. ;
  682. devcmd_devicequery:
  683.  bug     <"cnet: cmd_devicequery",10>
  684.  move.l  A1,-(A7)
  685.  move.l  ios2_statdata(A1),A0    ; a0 = caller's buffer
  686.  move.l  (A0),D1                 ; D1 = buffer size
  687.  move.l  size_supplied(pc),D0
  688.  cmp.l   D0,D1                   ; enough space to store info?
  689.  bhs.s   .get
  690.  clr.l   S2DQ_SIZESUPPLIED(A0)   ; nope!
  691.  bra.s   .done
  692. .get:
  693.  lea     S2DQ_SIZESUPPLIED(A0),A1
  694.  lea     size_supplied(pc),A0
  695.  subq.l  #4,D0                   ; skip bytes_available
  696.  bra.s   .copy
  697. .copyloop:
  698.  move.b  (A0)+,(A1)+             ; copy info to caller's buffer
  699. .copy:
  700.  dbf     D0,.copyloop
  701. .done:
  702.  move.l  (A7)+,A1
  703.  bra     TermIO
  704.  
  705.  
  706.  
  707. ;==============================================
  708. ;           CMD_GETSTATIONADDRESS
  709. ;==============================================
  710. ;
  711. devcmd_getstationaddress:
  712.  bug     <"cnet: cmd_getstationaddress",10>
  713.  move.l  A1,-(A7)
  714.  move.l  io_device(A1),A0
  715.  lea     dd_stationaddress(A0),A0
  716.  move.l  A0,D1
  717.  lea     ios2_srcaddr(A1),A1
  718.  move.w  #ETHER_ADDR_SIZE-1,D0
  719. .copysrc:
  720.  move.b  (A0)+,(A1)+             ; source address = station address
  721.  dbf     d0,.copysrc
  722.  move.l  (A7),A1
  723.  lea     ios2_dstaddr(A1),A1
  724.  move.w  #ETHER_ADDR_SIZE-1,D0
  725.  move.l  D1,A0
  726. .copydst:
  727.  moveq   #0,d1
  728.  move.b  (A0)+,d1
  729.  move.b  d1,(A1)+                ; dest address = station address
  730.  dbf     d0,.copydst
  731.  move.l  (A7)+,A1
  732.  bra     TermIO
  733.  
  734.  
  735. ;==============================================
  736. ;             CMD_CONFIGINTERFACE
  737. ;==============================================
  738. ;
  739. ; NOTE: a default station address has already
  740. ;       been set by init_nic
  741. ;
  742. devcmd_configinterface:
  743.  bug     <"cnet: cmd_ConfigInterface",10>
  744.  move.l  a6,-(sp)
  745.  move.l  io_device(a1),a0
  746.  move.l  ios2_srcaddr(a1),d0
  747.  ble     .done                          ; check for valid address
  748.  move.l  d0,dd_stationaddress(a0)
  749.  move.w  ios2_srcaddr+4(a1),dd_stationaddress+4(a0)
  750.  move.l  execbase(pc),a6
  751.  jsr     _LVODisable(a6)
  752.  move.b  nic_cr,d1                      ; remember current command
  753.  delay
  754.  move.b  #DSCM_NODMA|DSCM_PG1,nic_cr    ; select bank 1
  755.  delay
  756.  move.b  dd_stationaddress+0(a0),nic_par0
  757.  delay
  758.  move.b  dd_stationaddress+1(a0),nic_par1
  759.  delay
  760.  move.b  dd_stationaddress+2(a0),nic_par2
  761.  delay                                     ; set station address
  762.  move.b  dd_stationaddress+3(a0),nic_par3
  763.  delay
  764.  move.b  dd_stationaddress+4(a0),nic_par4
  765.  delay
  766.  move.b  dd_stationaddress+5(a0),nic_par5
  767.  delay
  768.  move.b  d1,nic_cr                      ; restore command
  769.  jsr     _LVOEnable(a6)
  770.  bset    #DDB_CONFIGURED,dd_flags(a0)   ; now configured
  771. .done:
  772.  move.l  (sp)+,a6
  773.  bra     TermIO
  774.  
  775.  
  776.  
  777. ;==============================================
  778. ;              CMD_BROADCAST
  779. ;==============================================
  780. ;
  781. devcmd_broadcast:
  782.  bug     <"cnet: cmd_broadcast",10>
  783.  move.w  #ETHER_ADDR_SIZE-1,D0
  784.  moveq   #0,d1
  785. .loop:
  786.  move.b  #255,ios2_dstaddr(a1,d1.w)    ; dest address = BROADCAST
  787.  addq.w  #1,d1
  788.  dbf     d0,.loop
  789. .doit:
  790.  bra     devcmd_write
  791.  
  792.  
  793.  
  794. ;=========================================================
  795. ;                   CMD_TRACKTYPE
  796. ;=========================================================
  797. ;
  798. ; This function adds a packet type to the
  799. ; list of those that are being tracked.
  800. ;
  801. devcmd_tracktype:
  802.  bug     <"cnet: cmd_tracktype %ld",10>,ios2_packettype(a1)
  803.  bra     TermIO    ; but we won't actually track anything
  804.  
  805. ;=========================================================
  806. ;                   CMD_UNTRACKTYPE
  807. ;=========================================================
  808. ;
  809. ; This function removes a packet type from
  810. ; the list of those that are being tracked.
  811. ;
  812. devcmd_untracktype:
  813.  bug     <"cnet: cmd_untracktype %ld",10>,ios2_packettype(a1)
  814.  bra     TermIO    ; but we won't actually untrack anything
  815.  
  816. ;=========================================================
  817. ;              commands not supported
  818. ;=========================================================
  819. ;
  820. devcmd_nosupport:
  821.  bug     <"cnet: Unsupported command %d",10>,io_command-2(a1)
  822.  move.b  #S2ERR_NOT_SUPPORTED,io_error(a1)
  823.  moveq   #S2WERR_GENERIC_ERROR,d0
  824.  move.l  d0,ios2_wireerror(a1)
  825.  bra     TermIO
  826.  
  827.  
  828. ;==========================================================
  829. ;             doevent(device, events)
  830. ;                       a0      d0
  831. ;==========================================================
  832. ;
  833. ; called when an 'important' event occurs
  834. ;
  835. DoEvent:
  836.  bug     <"cnet: doevent $%08lx ...">,d0
  837.  movem.l D2/A2/A6,-(A7)
  838.  move.l  D0,D2
  839.  move.l  dd_eventlist(A0),A2     ; get first ioreq
  840.  move.l  execbase(PC),A6
  841.  jsr     _LVODisable(A6)         ; lock eventlist
  842.  bra.s   .start
  843. .loop:
  844.  move.l  ios2_wireerror(A2),D0
  845.  and.l   D2,D0                   ; ioreq for our events?
  846.  beq.s   .next
  847.  move.l  D0,ios2_wireerror(A2)   ; set the actual events
  848.  move.l  A2,A1
  849.  jsr     _LVORemove(A6)          ; remove ioreq from list
  850.  move.b  #NT_REPLYMSG,ln_type(A2)
  851.  move.l  A2,A1
  852.  bug     <"cnet: returned eventreq $%lx",10>,a1
  853.  move.l  execbase(PC),A6
  854.  jsr     _LVOReplyMsg(A6)        ; send reply to ioreq owner
  855. .next:
  856.  move.l  (A2),A2                 ; next ioreq
  857. .start:
  858.  tst.l   (A2)                    ; last ioreq ?
  859.  bne.s   .loop
  860. .done:
  861.  bug     <10,"cnet: doevent done",10>
  862.  jsr     _LVOEnable(A6)          ; unlock eventlist
  863.  movem.l (A7)+,D2/A2/A6
  864.  rts
  865.  
  866. ;======================
  867. ;  delay approx 1.5mS
  868. ;======================
  869. ;
  870. delay1500:
  871.  move.l   D0,-(A7)
  872.  move.w   #1500,D0
  873. .loop:
  874.  tst.b    $bfe001       ; wait 1uS
  875.  dbf      D0,.loop
  876.  move.l   (A7)+,D0
  877.  rts
  878.  
  879.  
  880.  
  881. ;==================================================================
  882. ;        RemoteRead(buffer, nicbuffer, length)
  883. ;                     a1       d0.w     d1.w
  884. ;==================================================================
  885. ;
  886. ; Get a copy of data stored in the network card's onboard RAM.
  887. ;
  888. ;  buffer     = Amiga RAM
  889. ;
  890. ;  nicbuffer  = 16 bit address in card memory
  891. ;
  892. RemoteRead:
  893.  addq.w  #1,d1                   ; bump up count to even value
  894.  bclr    #0,d1
  895.  delay
  896.  swap    d1
  897.  move.b  nic_cr,d1               ; save old command
  898.  swap    d1
  899.  delay
  900.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
  901.  delay
  902.  move.b  d1,nic_rbcr0            ;   set count.lo
  903.  ror.w   #8,D1
  904.  delay
  905.  move.b  d1,nic_rbcr1            ;   set count.hi
  906.  delay
  907.  move.b  d0,nic_rsar0            ;   set address.lo
  908.  ror.w   #8,D0
  909.  delay
  910.  move.b  D0,nic_rsar1            ;   set address.hi
  911.  delay
  912.  move.b  #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
  913.  ror.w   #8,d1
  914.  move.w  d1,d0
  915.  and.w   #%0000000000011110,d0
  916.  neg.w   d0
  917.  lsr.w   #5,d1
  918.  lea     nic_data,a0
  919.  jmp     .startread(pc,d0.w)
  920. .dmaread:
  921.  move.w  (A0),(A1)+
  922.  move.w  (A0),(A1)+
  923.  move.w  (A0),(A1)+
  924.  move.w  (A0),(A1)+
  925.  move.w  (A0),(A1)+
  926.  move.w  (A0),(A1)+
  927.  move.w  (A0),(A1)+
  928.  move.w  (A0),(A1)+
  929.  move.w  (A0),(A1)+
  930.  move.w  (A0),(A1)+
  931.  move.w  (A0),(A1)+
  932.  move.w  (A0),(A1)+
  933.  move.w  (A0),(A1)+
  934.  move.w  (A0),(A1)+
  935.  move.w  (A0),(A1)+
  936.  move.w  (A0),(A1)+
  937. .startread:
  938.  dbf     d1,.dmaread
  939.  move.b  #DSIS_RDC,nic_isr       ; Remote DMA Complete
  940.  swap    d1
  941.  delay
  942.  move.b  d1,nic_cr               ; restore old command
  943.  rts
  944.  
  945.  
  946.  
  947. ;=================================================================
  948. ;         RemoteWrite( buffer, nicbuffer, count )
  949. ;                        a1      d0.w     d1.w
  950. ;=================================================================
  951. ;
  952. ;      Puts data into the network card's onboard RAM
  953. ;
  954. ;  buffer    = Amiga memory
  955. ;
  956. ;  nicbuffer = 16 bit address in card RAM
  957. ;
  958. ;
  959. RemoteWrite:
  960.  addq.w  #1,D1
  961.  bclr    #0,D1                      ; bump up count to even value
  962.  swap    d1
  963.  delay
  964.  move.b  nic_cr,d1                  ; save old command
  965.  swap    d1
  966.  delay
  967.  move.b  #DSIS_RDC,nic_isr          ; remote DMA complete
  968.  delay
  969.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; select bank 0
  970.  delay
  971.  move.b  D0,nic_rsar0               ; set address.lo
  972.  lsr.w   #8,D0
  973.  delay
  974.  move.b  D0,nic_rsar1               ; set address.hi
  975.  delay
  976.  move.b  D1,nic_rbcr0               ; set count.lo
  977.  ror.w   #8,D1
  978.  delay
  979.  move.b  D1,nic_rbcr1               ; set count.hi
  980.  delay
  981.  move.b  #DSCM_START|DSCM_RWRITE,nic_cr ; request remote write
  982.  ror.w   #8,D1
  983.  move.w  d1,d0
  984.  and.w   #%0000000000011110,d0
  985.  neg.w   d0
  986.  lsr.w   #5,d1
  987.  lea     nic_data,a0
  988.  jmp     .startwrite(pc,d0.w)
  989. .dmawrite:
  990.  move.w  (A1)+,(A0)
  991.  move.w  (A1)+,(A0)
  992.  move.w  (A1)+,(A0)
  993.  move.w  (A1)+,(A0)
  994.  move.w  (A1)+,(A0)
  995.  move.w  (A1)+,(A0)
  996.  move.w  (A1)+,(A0)
  997.  move.w  (A1)+,(A0)
  998.  move.w  (A1)+,(A0)
  999.  move.w  (A1)+,(A0)
  1000.  move.w  (A1)+,(A0)
  1001.  move.w  (A1)+,(A0)
  1002.  move.w  (A1)+,(A0)
  1003.  move.w  (A1)+,(A0)
  1004.  move.w  (A1)+,(A0)
  1005.  move.w  (A1)+,(A0)
  1006. .startwrite:
  1007.  dbf     d1,.dmawrite
  1008.  move.w  #30000,D0                  ; set timeout
  1009. .check:
  1010.  delay
  1011.  move.b  nic_isr,d1                 ; wait for remote DMA complete
  1012.  and.b   #DSIS_RDC,d1
  1013.  bne.s   .OK
  1014.  dbf     D0,.check
  1015.  moveq   #1,D0                      ; timed out error
  1016.  bra.s   .done
  1017. .ok:
  1018.  moveq   #0,D0                      ; OK
  1019. .done:
  1020.  delay
  1021.  move.b  #DSIS_RDC,nic_isr          ; Remote DMA complete
  1022.  swap    d1
  1023.  delay
  1024.  move.b  d1,nic_cr                  ; restore old command
  1025.  rts
  1026.  
  1027.  
  1028. ;=========================================================
  1029. ;                      reset_nic()
  1030. ;=========================================================
  1031. ;
  1032. reset_nic:
  1033.  delay
  1034.  move.b  nic_rst,D0                       ; start reset pulse
  1035.  delay
  1036.  move.b  D0,nic_rst                       ; end reset pulse
  1037.  delay
  1038.  move.b  #DSCM_NODMA|DSCM_STOP,nic_cr     ; stop controller
  1039.  bsr     delay1500                        ; wait 1.5mS
  1040.  move.b  #$ff,nic_isr                     ; clear all nic ints
  1041.  rts
  1042.  
  1043.  
  1044. ;========================================================================
  1045. ;                           init_nic(device)
  1046. ;                                      a1
  1047. ;========================================================================
  1048. ;
  1049. ;            set up the network card for online operation
  1050. ;
  1051. ; Here we also get the hardware station address from the nic's ROM. The
  1052. ; CNet card sometimes doesn't read its ROM correctly, so in this case we
  1053. ; use a fixed address instead.
  1054. ;
  1055. init_nic:
  1056.  bug     <"cnet: init_nic   ">
  1057.  movem.l D2/A5/A6,-(A7)
  1058.  move.l  A1,A5                             ; a5 = device data
  1059.  move.l  execbase(PC),A6
  1060.  jsr     _LVODisable(A6)                   ; ignore ints while setting up
  1061.  btst    #DDB_NICUP,dd_flags(a5)
  1062.  bne     .ok                               ; already initialised ?
  1063.  move.b  #DSDC_WTS|DSDC_FT1|DSDC_BMS,dd_dcr(A5)  ; Word Xfer, FIFO, Burst
  1064.  move.b  #DSRC_AB,dd_rcr(A5)                     ; accept broadcast packets
  1065.  move.b  #INTMASK,dd_imr(A5)                     ; accept useful interrupts
  1066.  bsr     reset_nic                         ; reset the controller
  1067.  delay
  1068.  move.b  nic_cr,D0                         ; get command
  1069.  cmp.b   #DSCM_NODMA|DSCM_STOP,d0
  1070.  bne     .error                            ; is it correct ?
  1071.  delay
  1072.  move.b  dd_dcr(A5),nic_dcr                ; set data configuration register
  1073.  delay
  1074.  move.b  #0,nic_rbcr0                      ; clear remote byte count
  1075.  delay
  1076.  move.b  #0,nic_rbcr1                      ;         ''
  1077.  delay
  1078.  move.b  #DSRC_MON,nic_rcr                 ; set rx to monitor mode
  1079.  delay
  1080.  move.b  #DSTC_LB0,nic_tcr                 ; set tx to loopback mode 1
  1081.  delay
  1082.  move.b  #(RBUFEND/256)-1,nic_bnry         ; set boundary page
  1083.  delay
  1084.  move.b  #RBUF/256,nic_pstart              ; set start of rx ring buffer
  1085.  delay
  1086.  move.b  #RBUFEND/256,nic_pstop            ; set end of rx ring buffer
  1087.  delay
  1088.  move.b  #$ff,nic_isr                      ; clear all interrupts
  1089.  delay
  1090.  move.b  #0,nic_imr                        ; no interrupts allowed
  1091.  delay
  1092.  move.b  nic_rsr,d0
  1093.  delay
  1094.  move.b  nic_ncr,d0
  1095.  delay
  1096.  move.b  nic_cntr0,d0                      ; read status registers
  1097.  delay
  1098.  move.b  nic_cntr1,d0
  1099.  delay
  1100.  move.b  nic_cntr2,d0
  1101.  delay
  1102.  move.b  #ETHER_ADDR_SIZE*2,nic_rbcr0      ; byte count low = (words)
  1103.  delay
  1104.  move.b  #0,nic_rbcr1                      ; byte count high = 0
  1105.  delay
  1106.  move.b  #0,nic_rsar0                      ; remote start addr low = 0 (ROM)
  1107.  delay
  1108.  move.b  #0,nic_rsar1                      ; remote start addr high = 0 (ROM)
  1109.  delay
  1110.  move.b  #DSCM_RREAD,nic_cr                ; start remote read to get
  1111.  delay                                     ; station address from ROM
  1112.  lea     dd_romstationaddress(a5),A0
  1113.  move.w  #ETHER_ADDR_SIZE-1,D0
  1114. .getaddr:
  1115.  move.b  nic_data,(A0)+                    ; get ROM station address
  1116.  dbf     D0,.getaddr                       ; NOTE: 'move.b' as ROM is 8 bit
  1117.  move.w  #30000,d1
  1118. .waitloop:
  1119.  delay
  1120.  move.b  nic_isr,d0
  1121.  and.b   #DSIS_RDC,d0                      ; wait for remote DMA complete
  1122.  dbne    d1,.waitloop
  1123.  tst.b   d0
  1124.  beq     .error                            ; error if timed out
  1125.  delay
  1126.  move.b  #DSIS_RDC,nic_isr                 ; clear remote DMA complete int
  1127.  lea     dd_romstationaddress(a5),a0
  1128.  btst    #7,(a0)
  1129.  bne.s   .badaddr                          ; good station address ?
  1130.  move.l  2(a0),d0
  1131.  beq.s   .badaddr
  1132.  cmp.l   #-1,d0
  1133.  bne.s   .gotstation
  1134. .badaddr:
  1135.  lea     default_address(pc),a0            ; use known good station address
  1136. .gotstation:
  1137.  lea     dd_stationaddress(a5),a1
  1138.  moveq   #ETHER_ADDR_SIZE-1,d0
  1139. .copyaddr:
  1140.  move.b  (a0)+,(a1)+                       ; copy address to device data
  1141.  dbf     d0,.copyaddr
  1142.  delay
  1143.  move.b  #DSCM_NODMA|DSCM_PG1|DSCM_STOP,nic_cr ; select bank 1
  1144.  delay
  1145.  move.b  dd_stationaddress+0(a5),nic_par0
  1146.  delay
  1147.  move.b  dd_stationaddress+1(a5),nic_par1
  1148.  delay
  1149.  move.b  dd_stationaddress+2(a5),nic_par2
  1150.  delay                                     ; set station address
  1151.  move.b  dd_stationaddress+3(a5),nic_par3
  1152.  delay
  1153.  move.b  dd_stationaddress+4(a5),nic_par4
  1154.  delay
  1155.  move.b  dd_stationaddress+5(a5),nic_par5
  1156.  delay
  1157.  move.b  #RBUF/256,nic_curr                ; set current page for rx
  1158.  move.b  #DSCM_NODMA|DSCM_START,d0
  1159.  delay
  1160.  move.b  d0,nic_cr                         ; start controller
  1161.  delay
  1162.  cmp.b   nic_cr,D0
  1163.  bne     .error                            ; command accepted ?
  1164.  delay
  1165.  move.b  dd_rcr(A5),nic_rcr                ; normal rx mode
  1166.  delay
  1167.  move.b  #0,nic_tcr                        ; loopback mode off
  1168.  delay
  1169.  move.b  #TBUF/256,nic_tpsr                ; init tx start page
  1170.  delay
  1171.  move.b  #$ff,nic_isr                      ; clear all interrupts
  1172.  delay
  1173.  move.b  dd_imr(A5),nic_imr                ; enable nic interrupts
  1174. .ok:
  1175.  bset    #DDB_NICUP,dd_flags(a5)           ; nic is initialised
  1176.  bug     <"OK",10>
  1177.  moveq   #0,D0
  1178.  bra.s   .done                             ; return OK
  1179. .error:
  1180.  bsr     reset_nic                         ; reset nic after malfunction
  1181. .bad:
  1182.  bug     <"failed",10>
  1183.  moveq   #-1,D0                            ; return error
  1184. .done:
  1185.  jsr     _LVOEnable(A6)                    ; allow interrupt processing
  1186.  movem.l (A7)+,D2/A5/A6
  1187.  rts
  1188.  
  1189.  
  1190. ;========================================================
  1191. ;                 txintcode(device)
  1192. ;                             a1
  1193. ;========================================================
  1194. ;
  1195. ;  send packets to network card. packets will be put
  1196. ;  into the card's onboard 16 bit ram, and then
  1197. ;  transmitted to the wire.
  1198. ;
  1199. txintcode:
  1200.  movem.l D4-D7/A2-A4/A6,-(A7)
  1201.  move.l  A1,A4                      ; a4 = device
  1202. .next:
  1203.  btst    #DDB_TX,dd_flags(a4)       ; quit if tx in progress (status int
  1204.  bne     .done                      ; will restart us when tx complete)
  1205. .getreq:
  1206.  lea     dd_writelist(A4),A0
  1207.  move.l  execbase(pc),a6            ; remove top ioreq
  1208.  jsr     _LVORemHead(A6)
  1209.  tst.l   D0                         ; any ioreqs to process?
  1210.  beq     .done
  1211.  move.l  D0,A3                      ; A3 = ioreq
  1212.  lea     txbuffer,A1                ; A1 = our internal packet buffer
  1213.  btst    #SANA2IOB_RAW,io_flags(A3) ; raw packets?
  1214.  beq.s   .notraw
  1215.  move.l  ios2_datalength(A3),D6     ; raw packet is full length
  1216.  bra.s   .send
  1217. .notraw:
  1218.  lea     ios2_dstaddr(A3),A0
  1219.  moveq   #ETHER_ADDR_SIZE-1,D0
  1220. .copy1:
  1221.  move.b  (A0)+,(A1)+                ; insert dest stationaddr into packet
  1222.  dbra    D0,.copy1
  1223.  lea     dd_stationaddress(A4),A0
  1224.  moveq   #ETHER_ADDR_SIZE-1,D0
  1225. .copy2:
  1226.  move.b  (A0)+,(A1)+                ; insert src address into packet
  1227.  dbra    D0,.copy2
  1228.  move.l  ios2_packettype(A3),D0     ; insert packettype into packet
  1229.  move.w  D0,(A1)+
  1230.  moveq   #ether_data,D6
  1231.  add.l   ios2_datalength(A3),D6     ; d6 = length of header + data
  1232. .send:
  1233.  move.l  a1,a0
  1234.  move.l  ios2_data(A3),A1
  1235.  move.l  ios2_datalength(A3),D0
  1236.  move.l  ios2_buffermanagement(a3),a2
  1237.  move.l  bufman_copyfrombuf(a2),a2
  1238.  jsr     (a2)                       ; call copyfrombuf
  1239.  moveq   #ETHER_MIN_LEN,D0
  1240.  cmp.l   D0,D6
  1241.  bge.s   .min                       ; d6 adjusted to legal packet size
  1242.  move.l  D0,D6
  1243. .min:
  1244. ; bug     <"cnet: writepacket %ld bytes",10>,d6
  1245.  move.l  D6,D1
  1246.  move.w  #TBUF,d0
  1247.  lea     txbuffer,A1
  1248.  bsr     RemoteWrite                ; put packet into nic tx buffer
  1249.  tst.l   D0
  1250.  bne.s   .termio
  1251.  move.l  execbase(PC),A6            ; disable interrupts during tx setup
  1252.  jsr     _LVODisable(A6)
  1253.  bset    #DDB_TX,dd_flags(A4)       ; set our "buffer full" flag
  1254.  delay
  1255.  move.b  D6,nic_tbcr0               ; set tx byte count lo
  1256.  ror.w   #8,D6
  1257.  delay
  1258.  move.b  D6,nic_tbcr1               ; set tx byte count hi
  1259.  delay
  1260.  move.b  #DSCM_NODMA|DSCM_TRANS|DSCM_START,nic_cr ; start tx
  1261.  move.l  execbase(PC),A6
  1262.  jsr     _LVOEnable(A6)             ; enable interrupts
  1263. .termio:
  1264.  move.l  A3,A1
  1265.  bsr     TermIO                     ; finish IOrequest
  1266.  bra     .next                      ; process next ioreq
  1267. .done:
  1268.  movem.l (A7)+,D4-D7/A2-A4/A6
  1269.  moveq   #0,d0
  1270.  rts
  1271.  
  1272.  
  1273. ;============================================================
  1274. ;                   rxintcode(device)
  1275. ;                               a1
  1276. ;============================================================
  1277. ;
  1278. ;                service rx interrupts
  1279. ;
  1280. rxintcode:
  1281.  movem.l D6/D7/A3-A6,-(A7)
  1282.  move.l  A1,A3                             ; a3 = device
  1283.  move.l  execbase(PC),A6
  1284. .nextpage:
  1285.  jsr     _LVODisable(A6)
  1286.  delay
  1287.  move.b  #DSCM_NODMA|DSCM_PG1|DSCM_START,nic_cr ; select bank 1
  1288.  moveq   #0,D7
  1289.  move.b  nic_curr,D7                       ; d7 = current page
  1290.  delay
  1291.  move.b  #DSCM_NODMA|DSCM_START,nic_cr     ; select bank 0
  1292.  jsr     _LVOEnable(A6)
  1293.  moveq   #0,D6
  1294.  delay
  1295.  move.b  nic_bnry,D6
  1296.  addq.w  #1,D6                             ; d6 = next page (boundary+1)
  1297.  cmp.w   #RBUFEND/256,D6
  1298.  blo.s   .nowrap                           ; end of buffer mem  ?
  1299.  moveq   #RBUF/256,D6                      ; wrap around to start
  1300. .nowrap:
  1301.  cmp.w   D6,D7                             ; current page = next page ?
  1302.  beq     .done                             ; if so then nothing to get
  1303.  move.w  D6,D0
  1304.  asl.w   #8,D0                             ; d0 = 16 bit page address
  1305.  lea     rx_header(pc),A1                  ; a1 = buffer
  1306.  moveq   #20,D1                            ; 20 bytes to get
  1307.  bsr     RemoteRead                        ; get packet header
  1308.  move.b  rx_header+prhdr_status(pc),d0
  1309.  and.b   #DSRS_RPC,d0                      ; complete packet received ?
  1310.  bne.s   .goodpacket
  1311.  addq.l  #1,dd_errors(a3)                  ; another packet error
  1312.  bra.s   .next
  1313. .goodpacket:
  1314.  move.l  A3,A0
  1315.  move.w  D6,D0
  1316.  lea     rx_header(pc),A1
  1317.  bsr     readpacket                        ; read whole packet into ioreqs
  1318. .next:
  1319.  moveq   #0,D0
  1320.  move.b  rx_header+prhdr_nxtpg(pc),D0      ; get next page number
  1321.  move.w  D0,D7
  1322.  subq.w  #1,D0                             ; nxtpage-1 = new boundary
  1323.  cmp.w   #RBUF/256,D0
  1324.  bge.s   .boundary                         ; wrap if before 1st page
  1325.  moveq   #(RBUFEND/256)-1,D0
  1326. .boundary:
  1327.  delay
  1328.  move.b  D0,nic_bnry                       ; set new boundary
  1329.  bra     .nextpage                         ; back for more
  1330. .done:
  1331.  delay
  1332.  move.b  #DSCM_NODMA|DSCM_START,nic_cr     ; select bank 0
  1333.  jsr     _LVODisable(A6)
  1334.  delay
  1335.  move.b  nic_rsr,d0                        ; read rx status
  1336.  delay
  1337.  move.b  nic_cntr0,D0
  1338.  delay
  1339.  move.b  nic_cntr1,D0                      ; read counters
  1340.  delay
  1341.  move.b  nic_cntr2,D0
  1342.  or.b    #DSIM_OVWE|DSIM_RXEE|DSIM_PRXE,dd_imr(A3)
  1343.  move.b  dd_imr(a3),nic_imr                ; allow rx interrupts
  1344.  jsr     _LVOEnable(A6)
  1345.  movem.l (A7)+,D6/D7/A3-A6
  1346.  moveq   #0,D0
  1347.  rts
  1348.  
  1349.  
  1350. ;==============================================================
  1351. ;             readpacket( device, pkthdr, page )
  1352. ;                           a0     a1     d0.w
  1353. ;==============================================================
  1354. ;
  1355. ; get packet from network card and feed it to next ioreq
  1356. ;
  1357. ; Inputs:
  1358. ;
  1359. ;       pkthdr = packet header info extracted from nic
  1360. ;
  1361. ;       page = 256 byte page in nic RAM that holds packet
  1362. ;
  1363. ;
  1364. readpacket:
  1365.  movem.l D3-D7/A2-A6,-(A7)
  1366.  move.l  D0,D7                          ; D7 = page
  1367.  move.l  A0,A5                          ; A5 = device
  1368.  move.l  A1,A4                          ; a4 = header
  1369.  moveq   #0,D6
  1370.  move.b  prhdr_sz1(A4),D6
  1371.  lsl.w   #8,D6                          ; D6 = packet data length
  1372.  move.b  prhdr_sz0(A4),D6
  1373.  sub.w   #prhdr_sizeof+ether_data,D6    ; D6 = length of user data
  1374.  moveq   #0,D3
  1375.  move.w  prhdr_sizeof+ether_type(A4),D3 ; d3 = type
  1376. ; bug     <"cnet: readpacket type %ld, %ld bytes",10>,d3,d6
  1377.  move.l  dd_readlist(A5),A3             ; a3 = first ioreq
  1378.  bra.s   .getreq                        ; find a suitable ioreq
  1379. .checkreq:
  1380.  cmp.l   ios2_packettype(A3),D3         ; does it want our packet ?
  1381.  beq.s   .gotreq
  1382.  cmp.w   #1500,d3
  1383.  bhi.s   .nextreq                       ; accept 802.3 packets
  1384.  cmp.l   #1500,ios2_packettype(A3)
  1385.  bls.s   .gotreq
  1386. .nextreq:
  1387.  move.l  D1,A3                          ; a3 = next ioreq in list
  1388. .getreq:
  1389.  move.l  (A3),D1                        ; end of list ?
  1390.  bne.s   .checkreq
  1391.  bra     .done
  1392. .gotreq:
  1393.  move.l  A3,A1
  1394.  move.l  execbase(PC),A6
  1395.  jsr     _LVORemove(A6)                 ; remove ioreq from list
  1396.  lea     ios2_dstaddr(A3),A0
  1397.  moveq   #ETHER_ADDR_SIZE-1,D0
  1398. .dst:
  1399.  move.b  (A4)+,(A0)+                    ; extract the dest address
  1400.  dbf     D0,.dst
  1401.  cmp.w   #$ffff,ios2_dstaddr(a3)
  1402.  bne.s   .getsrc                        ; address = Broadcast ?
  1403.  cmp.l   #$ffffffff,ios2_dstaddr+2(a3)
  1404.  bne.s   .getsrc
  1405.  bset    #SANA2IOB_BCAST,io_flags(a3)   ; set BROADCAST flag in ioreq
  1406. .getsrc:
  1407.  lea     ios2_srcaddr(A3),A0
  1408.  moveq   #ETHER_ADDR_SIZE-1,D0
  1409. .src:
  1410.  move.b  (A4)+,(A0)+                    ; extract the src address
  1411.  dbf     D0,.src
  1412.  move.w  D7,D5
  1413.  asl.w   #8,D5                          ; address=page*256
  1414.  add.w   #prhdr_sizeof+ether_data,D5    ; skip pageheader and etherheader
  1415.  btst    #SANA2IOB_RAW,io_flags(A3)
  1416.  beq.s   .getpacket                     ; is etherheader wanted ?
  1417.  moveq   #ether_data,D0
  1418.  add.l   D0,D6                        ; add header length for raw packet
  1419.  sub.w   D0,D5                        ; backup nic address to include header
  1420. .getpacket:
  1421.  lea     rxbuffer,A1
  1422.  move.w  D5,D0
  1423.  move.w  D6,D1
  1424.  bsr     RemoteRead                   ; get packet from network card's RAM
  1425.  move.l  ios2_data(A3),A0
  1426.  lea     rxbuffer,A1
  1427.  move.l  D6,ios2_datalength(A3)       ; set data length in ioreq
  1428.  move.l  d6,d0
  1429.  move.l  ios2_buffermanagement(a3),a2
  1430.  move.l  bufman_copytobuf(a2),a2
  1431.  jsr     (a2)                         ; call copytobuf
  1432.  move.l  A3,A1
  1433.  bsr     TermIO                       ; IO finished
  1434. .done:
  1435.  movem.l (A7)+,D3-D7/A2-A6
  1436.  rts
  1437.  
  1438. ;======================================================================
  1439. ;                  init_card(device)
  1440. ;                              a1
  1441. ;======================================================================
  1442. ;
  1443. ;                    Initialise PCMCIA card
  1444. ;
  1445. init_card:
  1446.  bug     <"cnet: init_card  ">
  1447.  movem.l D3-D6/A3/A6,-(A7)
  1448.  move.l  a1,a3                        ; a3 = device
  1449.  btst    #DDB_OWNED,dd_flags(a3)      ; do we own the card already?
  1450.  bne     .owned
  1451.  move.l  dd_cardres(a3),d0
  1452.  bne.s   .gotres
  1453.  lea     cardname(pc),a1
  1454.  move.l  execbase(pc),a6
  1455.  jsr     _LVOOpenResource(a6)         ; open credit card resource
  1456.  move.l  d0,dd_cardres(a3)
  1457.  beq     .error
  1458. .gotres:
  1459.  lea     dd_cardhandle(a3),a1
  1460.  lea     dd_cardremoved(a3),a0        ; init interrupt for card removed
  1461.  move.l  a3,is_data(a0)
  1462.  move.l  #card_removed_code,is_code(a0)
  1463.  move.l  a0,cah_CardRemoved(a1)
  1464.  lea     dd_cardinserted(a3),a0       ; init interrupt for card inserted
  1465.  move.l  a3,is_data(a0)
  1466.  move.l  #card_inserted_code,is_code(a0)
  1467.  move.l  a0,cah_CardInserted(a1)
  1468.  lea     dd_cardstatus(a3),a0         ; init interrupt for status change
  1469.  move.l  a3,is_data(a0)
  1470.  move.l  #status_int_code,is_code(a0)
  1471.  move.l  a0,cah_CardStatus(a1)
  1472.  lea     devicename(pc),a0
  1473.  move.l  a0,ln_name(a1)
  1474.  move.b  #20,ln_pri(a1)               ; high priority for I/O card
  1475.  move.b  #CARDF_IFAVAILABLE,cah_cardflags(a1)
  1476.  move.l  dd_cardres(a3),a6
  1477.  jsr     _LVOOwnCard(a6)              ; own card (sets up interrupt vectors)
  1478.  tst.l   d0
  1479.  bne     .error
  1480.  bset    #DDB_CARDIN,dd_flags(a3)     ; card is inserted
  1481.  bset    #DDB_OWNED,dd_flags(a3)      ; card is now owned by us
  1482. .owned:
  1483.  lea     dd_cardhandle(a3),a1
  1484.  lea     tuple(pc),a0
  1485.  moveq   #CISTPL_FUNC_ID,d1
  1486.  moveq   #40,d0
  1487.  move.l  dd_cardres(a3),a6
  1488.  jsr     _LVOCopyTuple(a6)            ; read function tuple
  1489.  tst.l   d0
  1490.  beq     .error
  1491.  lea     tuple(pc),a0
  1492.  move.b  2(a0),d0
  1493.  cmp.b   #CISTPL_FUNCID_NETWORK,d0    ; must be a network card!
  1494.  bne     .error
  1495.  lea     dd_cardhandle(a3),a1
  1496.  lea     tuple(pc),a0
  1497.  moveq   #CISTPL_CONF_MAP,d1
  1498.  moveq   #40,d0
  1499.  move.l  dd_cardres(a3),a6
  1500.  jsr     _LVOCopyTuple(a6)            ; read config map tuple
  1501.  tst.l   d0
  1502.  beq     .error
  1503.  lea     tuple(pc),a0
  1504.  move.b  2(a0),d0
  1505.  and.w   #$03,d0                      ; (number of address bytes)-1
  1506.  moveq   #0,d5
  1507. .getaddr:
  1508.  lsl.l   #8,d5
  1509.  move.b  4(a0,d0.w),d5                ; extract config register address
  1510.  dbf     d0,.getaddr
  1511.  and.l   #$0001FFFF,d5                ; limit to attribute memory range
  1512.  lea     dd_cardhandle(a3),a1
  1513.  moveq   #CISTPL_CONFIG,d1
  1514.  moveq   #40,d0
  1515.  jsr     _LVOCopyTuple(a6)            ; read 1st config tuple
  1516.  tst.l   d0
  1517.  beq.s   .error
  1518.  lea     dd_cardhandle(a3),a1
  1519.  move.l  #CARDF_DISABLE_WP|CARDF_ENABLE_DIGAUDIO,d1
  1520.  jsr     _LVOCardMiscControl(a6)      ; enable card I/O functions
  1521.  lea     tuple(pc),a0
  1522.  move.b  2(a0),d0                     ; extract configuration ID value
  1523. .setconfig:
  1524.  and.b   #$3f,d0
  1525.  lea     AttrMem,a0
  1526.  add.l   d5,a0
  1527.  move.b  d0,(a0)                      ; put ID into card config register
  1528.  bra.s   .ok
  1529. .error:
  1530.  bug     <"failed",10>
  1531.  moveq   #-1,d0                       ; card not available, return error
  1532.  bra.s   .done
  1533. .ok:
  1534.  bug     <"OK",10>
  1535.  moveq   #0,D0                        ; card is active, return OK
  1536. .done:
  1537.  movem.l (A7)+,D3-D6/A3/A6
  1538.  rts
  1539.  
  1540.  
  1541. ;=================================================================
  1542. ;              initialise device data structures
  1543. ;=================================================================
  1544. ;
  1545. ;   init_device(device)
  1546. ;                 a1
  1547. ;
  1548. init_device:
  1549.  move.l  A3,-(A7)
  1550.  move.l  A1,A3
  1551.  bset    #DDB_DEVINIT,dd_flags(A3)     ; already initialised ?
  1552.  bne     .done
  1553.  lea     dd_readlist(A3),A0
  1554.  move.l  A0,mlh_tailpred(A0)
  1555.  lea     mlh_tail(A0),A1               ; New MinList for read queue
  1556.  clr.l   (A1)
  1557.  move.l  A1,(A0)
  1558.  lea     dd_writelist(A3),A0
  1559.  move.l  A0,mlh_tailpred(A0)           ; New MinList for write queue
  1560.  lea     mlh_tail(A0),A1
  1561.  clr.l   (A1)
  1562.  move.l  A1,(A0)
  1563.  lea     dd_eventlist(A3),A0           ; New MinList for event queue
  1564.  move.l  A0,mlh_tailpred(A0)
  1565.  lea     mlh_tail(A0),A1
  1566.  clr.l   (A1)
  1567.  move.l  A1,(A0)
  1568.  lea     dd_bufmanlist(A3),A0          ; New MinList for bufman vectors
  1569.  move.l  A0,mlh_tailpred(A0)
  1570.  lea     mlh_tail(A0),A1
  1571.  clr.l   (A1)
  1572.  move.l  A1,(A0)
  1573.  move.b  #NT_INTERRUPT,dd_rxint+ln_type(a3)
  1574.  move.b  #16,dd_rxint+ln_pri(a3)
  1575.  lea     rxintname(pc),a0
  1576.  move.l  a0,dd_rxint+ln_name(a3)       ; set up rx swi
  1577.  lea     rxintcode(pc),a0
  1578.  move.l  a0,dd_rxint+is_code(a3)
  1579.  move.l  a3,dd_rxint+is_data(a3)
  1580.  move.b  #NT_INTERRUPT,dd_txint+ln_type(a3)
  1581.  move.b  #0,dd_txint+ln_pri(a3)
  1582.  lea     txintname(pc),a0
  1583.  move.l  a0,dd_txint+ln_name(a3)       ; set up tx swi
  1584.  lea     txintcode(pc),a0
  1585.  move.l  a0,dd_txint+is_code(a3)
  1586.  move.l  a3,dd_txint+is_data(a3)
  1587. .done:
  1588.  move.l  (A7)+,A3
  1589.  rts
  1590.  
  1591.  
  1592. ;============================================================
  1593. ;             PCMCIA status change interrupt
  1594. ;============================================================
  1595. ;
  1596. ;   Occurs whenever a PCMCIA status line changes
  1597. ;
  1598. ;   eg. when the network card activates it's interrupt line
  1599. ;
  1600. ;
  1601. ;  entry:   d0 = status change(s)
  1602. ;           a1 = device
  1603. ;
  1604. ;  exit:    d0 must be preserved!
  1605. ;
  1606. status_int_code:
  1607.  movem.l D2-D6/A2-A4,-(A7)
  1608.  move.l  D0,D6                      ; d6 = status changes
  1609.  move.l  A1,A4                      ; a4 = device
  1610.  btst    #DDB_NICUP,dd_flags(a4)    ; is nic working ?
  1611.  beq     .done
  1612.  
  1613.  move.b  nic_cr,d5                  ; save old command
  1614.  delay
  1615.  move.b  #0,nic_imr                 ; prevent nic interrupts
  1616.  bra     .checkint
  1617.  
  1618. ; interrupt service loop    (D3 = interrupt status)
  1619.  
  1620. .intloop:
  1621.  btst    #DSIB_ROVRN,d3
  1622.  beq     .no_overflow
  1623.  
  1624. ; receiver ring buffer overflowed (eek!)
  1625.  addq.l  #1,dd_overflows(a4)
  1626.  delay
  1627.  move.b  #0,nic_rbcr0
  1628.  delay
  1629.  move.b  #0,nic_rbcr1                  ; reset remote byte count
  1630.  delay
  1631.  move.b  #DSTC_LB0,nic_tcr
  1632.  delay                                 ; monitor mode
  1633.  move.b  #DSRC_MON,nic_rcr
  1634.  delay
  1635.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; try to restart controller
  1636.  delay
  1637.  move.b  #DSRC_AB,nic_rcr
  1638.  delay                                 ; normal rx mode
  1639.  move.b  #0,nic_tcr
  1640.  
  1641. .no_overflow:
  1642.  btst    #DSIB_RXE,d3
  1643.  beq.s   .norxerr
  1644.  addq.l  #1,dd_errors(a4)
  1645.  delay
  1646.  move.b  nic_rsr,d0                    ; read rx status
  1647.  delay
  1648.  move.b  nic_cntr0,D0
  1649.  delay
  1650.  move.b  nic_cntr1,D0                  ; read counters
  1651.  delay
  1652.  move.b  nic_cntr2,D0
  1653.  bra.s   .rx
  1654.  
  1655. .norxerr:
  1656.  btst    #DSIB_RX,d3
  1657.  beq.s   .no_rx
  1658.  
  1659. ; new packet(s) arrived in receive ring buffer
  1660. .rx:
  1661.  and.b   #~(DSIM_OVWE|DSIM_RXEE|DSIM_PRXE),dd_imr(A4) ; ignore rx ints
  1662.  lea     dd_rxint(A4),A1
  1663.  move.l  execbase(PC),A6
  1664.  jsr     _LVOCause(A6)            ; to copy packet(s) into waiting ioreqs
  1665.  
  1666. .no_rx:
  1667.  btst    #DSIB_TXE,d3
  1668.  bne.s   .tx
  1669.  btst    #DSIB_TX,d3
  1670.  beq     .no_tx
  1671.  
  1672. ; a packet has just been transmitted
  1673. .tx:
  1674.  moveq   #0,d0
  1675.  delay
  1676.  move.b  nic_ncr,d0               ; read collision count
  1677.  add.l   d0,dd_collisions(a4)
  1678.  bclr    #DDB_TX,dd_flags(A4)     ; buffer now free
  1679.  lea     dd_txint(A4),A1
  1680.  move.l  execbase(PC),A6
  1681.  jsr     _LVOCause(A6)            ; to transmit next packet
  1682.  
  1683. .no_tx:
  1684.  btst    #DSIB_CTRS,d3            ; counter overflow ?
  1685.  bne.s   .counter
  1686.  bra.s   .checkint                ; all ints processed
  1687.  
  1688. ; counter overflow
  1689. .counter:
  1690.  delay
  1691.  move.b  nic_cntr0,D0
  1692.  delay
  1693.  move.b  nic_cntr1,D0             ; read counters
  1694.  delay
  1695.  move.b  nic_cntr2,D0
  1696.  
  1697. .checkint:
  1698.  delay
  1699.  move.b  nic_isr,D3               ; D3 = nic interrupt status
  1700.  delay
  1701.  move.b  d3,nic_isr               ; clear current interrupt bit(s)
  1702.  and.b   dd_imr(a4),d3
  1703.  bne     .intloop                 ; any valid interrupts ?
  1704. .end:
  1705.  delay
  1706.  move.b  d5,nic_cr                ; restore old command
  1707.  eor.b   #$2c,d6
  1708.  or.b    #$c0,d6
  1709.  move.b  d6,$da9000               ; clear PCMCIA status change bits
  1710.  delay
  1711.  move.b  dd_imr(a4),nic_imr       ; enable nic interrupts
  1712.  moveq   #0,d0                    ; don't clear status bits coz we did
  1713. .done:
  1714.  movem.l (A7)+,D2-D6/A2-A4
  1715.  rts
  1716.  
  1717.  
  1718. ;============================================================
  1719. ;             PCMCIA Card Inserted interrupt
  1720. ;============================================================
  1721. ;
  1722. ;   Occurs whenever a PCMCIA card is plugged in
  1723. ;
  1724. ; NOTE: card.resource has given us ownership of the card
  1725. ;
  1726. ;  entry: a1 = device
  1727. ;
  1728. ;  exit:  d0,d1,a0,a1,a5,a6 = scratch
  1729. ;
  1730. card_inserted_code:
  1731.  bug     <"cnet: card inserted",10>
  1732.  move.l  a1,a5
  1733.  bset    #DDB_CARDIN,dd_flags(a5)      ; card is inserted
  1734.  bset    #DDB_OWNED,dd_flags(a5)       ; we own the card again
  1735.  bsr     init_card
  1736.  tst.l   d0                            ; attempt to init pcmcia card
  1737.  bne.s   .releasecard
  1738.  move.l  a5,a1
  1739.  bsr     init_nic                      ; attempt to start controller
  1740.  tst.l   d0
  1741.  beq.s   .good
  1742. .releasecard:
  1743.  lea     dd_cardhandle(a5),a1
  1744.  move.l  dd_cardres(a5),a6
  1745.  moveq   #0,d0
  1746.  jsr     _LVOReleaseCard(a6)           ; release foreign or bad card
  1747.  bclr    #DDB_OWNED,dd_flags(a5)
  1748.  bra.s   .done
  1749. .good:
  1750.  btst    #DDB_OFFLINE,dd_flags(a5)     ; has device been put offline ?
  1751.  bne.s   .done
  1752.  bset    #DDB_ONLINE,dd_flags(a5)      ; device is now online
  1753.  move.l  a5,a0
  1754.  moveq   #S2EVENT_ONLINE,D0
  1755.  bsr     DoEvent                       ; return ONLINE event
  1756. .done:
  1757.  rts
  1758.  
  1759. ;============================================================
  1760. ;             PCMCIA Card Removed interrupt
  1761. ;============================================================
  1762. ;
  1763. ;   Occurs whenever a PCMCIA card is unplugged
  1764. ;
  1765. card_removed_code:
  1766.  bug     <"cnet: card removed",10>
  1767.  move.l  a1,a5
  1768.  and.b   #~(DDF_OWNED!DDF_CARDIN!DDF_ONLINE!DDF_NICUP),dd_flags(a5)
  1769.  lea     dd_cardhandle(a5),a1
  1770.  move.l  dd_cardres(a5),a6
  1771.  moveq   #0,d0
  1772.  jsr     _LVOReleaseCard(a6)            ; release card
  1773.  move.l  a5,a0
  1774.  moveq   #S2EVENT_OFFLINE,D0
  1775.  bsr     DoEvent                        ; return OFFLINE event
  1776.  rts
  1777.  
  1778.  
  1779. rxintname:
  1780.  dc.b "cnet rx softint",0
  1781. txintname:
  1782.  dc.b "cnet tx softint",0
  1783.  
  1784. cardname:
  1785.  dc.b "card.resource",0
  1786.  
  1787. DeviceName:
  1788.  dc.b    "cnet.device",0
  1789. IDString:
  1790.  dc.b    "$VER: cnet.device "
  1791.  dc.b    (VERSION+"0"),".",(REVISION+"0")," "
  1792.  dc.b    __DATE
  1793.  dc.b    " by Bruce Abbott (bhabbott@inhb.co.nz)",10,0
  1794.  even
  1795.  
  1796. ; devicequery block
  1797.  
  1798. size_supplied:
  1799.  dc.l    S2DQ_SIZE            ; bytes supplied (size of this block)
  1800.  dc.l    0                    ; this is type 0
  1801.  dc.l    0                    ; this document is level 0
  1802.  dc.w    ETHER_ADDR_SIZE*8    ; address size in bits
  1803.  dc.l    ETHERPKT_SIZE        ; maximum packet data size
  1804.  dc.l    10000000             ; line rate (10 Megabits/sec)
  1805.  dc.l    S2WIRETYPE_ETHERNET  ; what the wire is
  1806.  
  1807.  
  1808. ; default station address to use if the card won't give it to us.
  1809.  
  1810. default_address:
  1811.  dc.b $00,$00,$12,$34,$56,$78 ; replace this with your card's address!
  1812.  
  1813.  
  1814. ;--------------------------------------------------------
  1815. ;                      Global data
  1816. ;--------------------------------------------------------
  1817.  
  1818. execbase    dc.l 0      ; local copy of execbase
  1819.  
  1820. tuple:
  1821.  ds.b    48             ; PCMCIA tuple buffer
  1822.  
  1823. rx_header:
  1824.  ds.b    20             ; received packet header
  1825.  
  1826. Endcode:
  1827.  
  1828.  section buffers,bss
  1829.  
  1830. rxbuffer:
  1831.  ds.b  1600             ; received packet buffer
  1832.  
  1833. txbuffer:
  1834.  ds.b  1600             ; transmit packet buffer
  1835.  
  1836.  
  1837.